package org.fing.edu.uy.esbadp.utils;

import java.io.StringReader;
import java.io.StringWriter;

import javax.xml.namespace.QName;
import javax.xml.stream.XMLEventReader;
import javax.xml.stream.XMLEventWriter;
import javax.xml.stream.XMLInputFactory;
import javax.xml.stream.XMLOutputFactory;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.events.EndElement;
import javax.xml.stream.events.StartElement;
import javax.xml.stream.events.XMLEvent;

import org.jboss.soa.esb.message.Message;

public class SoapExtraction {
	
	private static final XMLInputFactory XML_INPUT_FACTORY = getXmlInputFactory();
	private static final XMLOutputFactory XML_OUTPUT_FACTORY = getXmlOutputFactory();
	
	public static String findElementInBody(Message message, QName qname) throws XMLStreamException {		
		final XMLEventReader xmlReader = XML_INPUT_FACTORY.createXMLEventReader(new StringReader((String)message.getBody().get()));
		final StringWriter stringWriter = new StringWriter();
		final XMLEventWriter xmlWriter = XML_OUTPUT_FACTORY.createXMLEventWriter(stringWriter);
		
		boolean found = false;
		while(xmlReader.hasNext()){
			XMLEvent event = xmlReader.nextEvent();		
			if(isStartOfElement(event, qname)){				
		        do{
		        	xmlWriter.add(event);
		        	if(isEndOfElement(event, qname)){
		        		found = true;
		        	}
		        	event = xmlReader.nextEvent();
		        }while(xmlReader.hasNext() && !found);
		        xmlWriter.flush();
		        return stringWriter.toString();
			}
        }
		return null;
	}
	
	public static boolean isStartOfElement(final XMLEvent event, QName qname) {
        return event.isStartElement() && ((StartElement)event).getName().equals(qname);
    }
	
	public static boolean isEndOfElement(final XMLEvent event, QName qname) {
        return event.isEndElement() && ((EndElement)event).getName().equals(qname);
    }
    
    private static XMLOutputFactory getXmlOutputFactory() {
        final XMLOutputFactory factory = XMLOutputFactory.newInstance();
        // set any properies here if required before returning.
        return factory;
    }

    private static XMLInputFactory getXmlInputFactory() {
        final XMLInputFactory factory = XMLInputFactory.newInstance();
        // set any properies here if required before returning.
        return factory;
    }

}
